﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Transactions;
using NUnit.Framework;
using SimpleFS.Core;
using SimpleFS.Storage;
using SimpleFS.Services.Transactions;
using SimpleFS.Services.Transactions.Implementations;

namespace SimpleFS.Specs.Services.Transactions
{
    /// <summary>
    /// Atomic Operations for File:
    /// 1. Write
    /// 2. Delete
    /// 3. Rename
    /// </summary>
    [TestFixture]
    public class FileTest : AbstractFileSystemObjectTest
    {
        protected static readonly string sourceName = "../../Resources/source.txt";
        protected static readonly string targetName = "../../Resources/target.txt";

        protected IResourceManager resourceManager = null;

        public FileTest()
        {
            this.resourceManager = new SimpleResourceManager();
        }

        protected override IFileSystemObject SourceObject
        {
            get 
            { 
                return new SimpleFS.Services.Transactions.File(
                    new SimpleFS.Storage.Windows.File(sourceName), 
                    this.resourceManager);
            }
        }

        protected override IFileSystemObject TargetObject
        {
            get 
            {
                return new SimpleFS.Services.Transactions.File(
                    new SimpleFS.Storage.Windows.File(targetName), 
                    this.resourceManager);
            }
        }

        protected override void EnsureObjectExists(IFileSystemObject fileObject)
        {
            if (!System.IO.File.Exists(fileObject.Name))
            {
                FileStream stream = System.IO.File.Create(fileObject.Name);
                stream.Close();
            }
        }

        protected override void EnsureObjectIsDeleted(IFileSystemObject fileObject)
        {
            if (System.IO.File.Exists(fileObject.Name))
            {
                System.IO.File.Delete(fileObject.Name);
            }
        }

        [Test]
        public void TestWrite()
        {
            IFile sourceObject = this.SourceObject as IFile;
            IFile targetObject = this.TargetObject as IFile;

            Stream stream = sourceObject.Read();

            using (TransactionScope scope = new TransactionScope())
            {
                targetObject.Write(stream);
                scope.Complete();
            }
            Assert.IsTrue(targetObject.Exists());

            this.EnsureObjectIsDeleted(targetObject);

            using (TransactionScope scope = new TransactionScope())
            {
                targetObject.Write(stream);
            }
            Assert.IsFalse(targetObject.Exists());

            stream.Close();
        }

        [Test]
        public override void TestMove()
        {
            base.TestMove();
        }

        [Test]
        public override void TestCopy()
        {
            base.TestCopy();
        }

        [Test]
        public override void TestDelete()
        {
            base.TestDelete();
        }

        [Test]
        public override void TestRename()
        {
            base.TestRename();
        }

        [Test]
        public void TestWriteTwice()
        {
            IFile sourceObject = this.SourceObject as IFile;
            IFile targetObject = this.TargetObject as IFile;

            FileStream stream = System.IO.File.OpenRead("../../Resources/Hello.txt");

            using (TransactionScope scope = new TransactionScope())
            {
                sourceObject.Write(stream);
                targetObject.Write(stream);

                scope.Complete();
            }
        }
    }
}
